#include <semaphore.h>

#include "./Thread.h"
#include "./CurrentThread.h"

// 不能=赋值初始化不是标准对象初始化，如explicit用不了=初始化
std::atomic_int Thread::kNum{0};

Thread::Thread(ThreadFunc func, const std::string &name)
    : func_(std::move(func)), name_(name),
      isStart_(false), isJoin_(false), tid_(0)
{
    this->setDefaultName();
}

void Thread::setDefaultName()
{
    // 无论是否if都要增加
    // 可以放在构造而不是setDefaultName()，但要避免其他线程修改
    // 原子操作避免其他线程修改，线程的局部变量记录
    ++kNum;
    int num = kNum;
    // int num = kNum.load();

    if (this->name_.empty()) // ""返回true
    {
        char buf[32]{0};
        snprintf(buf, sizeof(buf), "Thread%d", num);
        this->name_ = buf;
    }
}

Thread::~Thread()
{
    // 析构时detach()，避免直接销毁线程，避免资源泄漏或未定义行为
    if (this->isStart_ && !this->isJoin_)
    {
        this->thread_->detach();
    }
}

std::string Thread::getName() const
{
    return this->name_;
}

bool Thread::getIsStart() const
{
    return this->isStart_;
}

pid_t Thread::getTid() const
{
    return this->tid_;
}

int Thread::getNum()
{
    return kNum;
}

void Thread::start()
{
    this->isStart_ = true;

    sem_t sem{};
    // 不涉及进程共享，初始值0
    ::sem_init(&sem, false, 0);

    // 运行线程
    // OPTIMIZE: 使用make_shared()而不是new创建智能指针
    // this->thread_ = std::shared_ptr<std::thread>(new std::thread([&]()
    this->thread_ = std::make_shared<std::thread>(
        [this, &sem]()
        {
            this->tid_ = CurrentThread::tid();

            ::sem_post(&sem);

            this->func_();
        });

    // 信号量实现同步，主线程等待子线程获取tid，否则被切换为别的线程导致获取tid错误
    // （C++20才有std::counting_semaphore）
    ::sem_wait(&sem);
}

void Thread::join()
{
    this->isJoin_ = true;
    this->thread_->join();
}